import java.io.*;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.*;
public class WorkWithFile 
{  
    private String work_direktory;// = "/home/tatyana/Documents/File_for_compressor/files/";
    private static long time_start = 0;
    private static long time_stop = 0;
    WorkWithFile(String work_direktory)
    {
        this.work_direktory = work_direktory;
    }
    public File createFile(String file_name)
    {
        String path_file = work_direktory + file_name;
        File file = new File(path_file); 
        return file;
    }
    synchronized public void PressFile(String command)
    {
            time_start = System.currentTimeMillis();
            try
            {
                System.out.print("\n Thread Runnable is started \n");
                Process process = Runtime.getRuntime().exec(command);
                System.out.print("\n Thread Runnable is finished \n");
                process.waitFor();
            }
            catch(IOException ex)
            {
                System.out.print("\n IOException in Thread " + ex + "\n");
            }
            catch(InterruptedException ex)
            {
                System.out.print("\n InterruptedException ex " + ex);
            }
            time_stop = System.currentTimeMillis();        
    }
    
    public long GetSizeFile(File file)
    {
        long file_size = 0;
        System.out.print("\n File size f: " + file.length() + "\n");
        if(!file.exists())
        {
            System.out.print("\n File " + file + " not exists" + " \n");
        }
        else
        {
            file_size = file.length();
        }
        return file_size;
    }
    
     public byte[] EncryptFile(String crypto_algorithm, SecretKey key, File file)//key_encription == key_decryption ?
    {
        try 
        {
            Cipher encrypt_cipher = Cipher.getInstance(crypto_algorithm);
            //SecretKey key = KeyGenerator.getInstance("DES").generateKey();
            encrypt_cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] crypto_text = encrypt_cipher.doFinal(ReadFile(file));
            //System.out.print("\n After encription file contents: " + new sun.misc.BASE64Encoder().encode(crypto_text));
            //return new sun.misc.BASE64Encoder().encode(crypto_text);
            return crypto_text;
       }
        catch(NoSuchAlgorithmException ex)
        {
            System.out.print("\n NoSuchAlgorithmException " + ex + "\n");
            return null;
        }
        catch (IllegalBlockSizeException ex) 
        {
            System.out.print("\n IllegalBlockSizeException " + ex + "\n");
            return null;
        } 
        catch(NoSuchPaddingException ex)
        {
            System.out.print("\n NoSuchPaddingException " + ex + "\n");
            return null;
        }
        catch(InvalidKeyException ex)
        {
            System.out.print("\n InvalidKeyException " + ex + "\n");
            return null;
        }
        catch (BadPaddingException ex) 
        {
            System.out.print("\n BadPaddingException " + ex + "\n");
            return null;
        }
        //byte[] crypto_text = crypto_algorithm.Encrypt(algorithm, key, ReadFile(file_name));
        //DataOutputStream output_stream = OpenFile(algorithm + file_name);
        //WriteBinaryFile(output_stream, crypto_text);
        //CloseFile(output_stream);
        //return crypto_text;
    }
     public byte[] DecryptFile(String crypto_algorithm, SecretKey key, byte[] crypto_text)
     {
        try 
        {
            Cipher decrypt_cipher = Cipher.getInstance(crypto_algorithm);
            decrypt_cipher.init(Cipher.DECRYPT_MODE, key);
            //byte[] enc = new sun.misc.BASE64Decoder().decodeBuffer(text_string);
            byte[] dec = decrypt_cipher.doFinal(crypto_text);
            //System.out.print("\n Text after decoding " + new String(dec));
            //return new String(dec, "UTF8");
            return dec;
        } 
        catch(NoSuchAlgorithmException ex)
        {
            System.out.print("\n NoSuchAlgorithmException " + ex + "\n");
            return null;
        }
        catch (IllegalBlockSizeException ex) 
        {
            System.out.print("\n IllegalBlockSizeException " + ex + "\n");
            return null;
        } 
        catch(NoSuchPaddingException ex)
        {
            System.out.print("\n NoSuchPaddingException " + ex + "\n");
            return null;
        }
        catch(BadPaddingException ex)
        {
            System.out.print("\n Exeption with bad padding " + ex + "\n");
            return null;
        }
        catch(InvalidKeyException ex)
        {
            System.out.print("\n InvalidKeyException " + ex + "\n");
            return null;
        }
         //byte[] decrypto_text = crypto_algorithm.Decrypt(algorithm, key, crypto_text);
         //DataOutputStream crypto_output_stream = OpenFile("dec" + algorithm + file_name);
         //WriteBinaryFile(crypto_output_stream, decrypto_text);
         //CloseFile(crypto_output_stream);
     }
     public SecretKey generateKey(String crypto_algorithm_name) 
    {
        try
        {
            SecretKey key = KeyGenerator.getInstance(crypto_algorithm_name).generateKey();
            return key;
        }
        catch(NoSuchAlgorithmException ex)
        {
            System.out.print("\n Exeption in algorithm of key generator " + ex + "\n");
            return null;
        }
    }
    public int CompressionRatio(File file, File arch_file)
    {
        float file_length = GetSizeFile(file);
        float arch_file_length = GetSizeFile(arch_file);
        float ratio = (file_length - arch_file_length)/file_length;
        int ratio_percent = (int)(ratio * 100);
        return ratio_percent;
    }
    public long TimeCompression()
    {
        return (time_stop - time_start);
     }
    public long Time(String command_compressing)
    {
        long time = 0;
        try
        {
            Process process = Runtime.getRuntime().exec("time -f %E " + command_compressing);
            process.waitFor();
            InputStream instream = process.getErrorStream();
            byte[] buf = new byte[instream.available()];
            instream.read(buf);
            String output_time =  new String(buf);
            RegularExpression regex = new RegularExpression();
            time = regex.splitTime(output_time);
            System.out.print("\n Time: " + time);
            return time;
        }
        catch(Exception ex)
        {
            System.out.print("\n Exception: " + ex);
            return time;
        }
    }
    public void DeleteFile(File file)
    {
        System.out.print("\n File " + file.getName() + " will be deleted \n");
        file.delete();
    }

    public byte[] ReadFile(File file)
    {
        FileInputStream in_stream = null;
        try
        {
            in_stream = new FileInputStream(file);
            byte[] buffer = new byte[in_stream.available()];
            in_stream.read(buffer);
            return buffer;
        }
        catch(FileNotFoundException ex)
        {
            System.out.print("\n File not Found Exception: " + ex);
            return null;
        }
        catch(IOException ex)
        {
            System.out.print("\n IOException: " + ex);
            return null;
        }
        finally
        {
              System.out.flush();
            try
            {
                in_stream.close();
            }
            catch(IOException ex)
            {
                System.out.print("\n IOException: " + ex);
                return null;
            }
        }
    }
    public void WriteBinaryFile(byte[] text, File file)
    {
        DataOutputStream out_stream = null;
        try
        {
            out_stream = new DataOutputStream(
                                          new BufferedOutputStream(
                                          new FileOutputStream(file)));
            out_stream.write(text);
            out_stream.flush();
        }
        catch(FileNotFoundException ex)
        {
            System.out.print("File " + file.getName() + " not found exception: " + ex);
        }
        catch(IOException ex)
        {
            System.out.print("Input/Output exception: " + ex);
        }
        finally
        {
            System.out.flush();
            try
            {
                out_stream.close();
            }
            catch(IOException ex)
            {
                System.out.print("\n IOException: " + ex);
            }
        }
    }
}